#include "IOchannel.h"
#include "Eventloop.h"
#include "EventloopProxy.h"
#include "IOchannelProxy.h"
#include "utility/assertion.h"

IOchannel::IOchannel(Eventloop &loop, int fd, std::string name):
    _name{std::move(name)}, _proxy{}, _fd{fd}, _inLoop{false}
{
    _proxy = std::make_unique<IOchannelProxy>(*this, loop.proxy()); 
}

IOchannel::~IOchannel() {
    assert(!_inLoop);
}

Eventloop &IOchannel::eventloop() const {
    return _proxy->eventloopProxy().eventloop();
}

void IOchannel::set_close_callback(const TrivialFunc &callback) {
    assert(callback);
    _proxy->set_close_callback(callback);
}

void IOchannel::set_error_callback(const TrivialFunc &callback) {
    assert(callback);
    _proxy->set_error_callback(callback);
}

void IOchannel::set_read_callback(const TimepointFunc &callback) {
    assert(callback);
    _proxy->set_read_callback(callback);
}

void IOchannel::set_write_callback(const TrivialFunc &callback) {
    assert(callback);
    _proxy->set_write_callback(callback);
}

void IOchannel::disable() {
    _proxy->disable();
    _update();
}

void IOchannel::disable_reading() {
    _proxy->disable_reading();
    _update();
}

void IOchannel::disable_writing() {
    _proxy->disable_writing();
    _update();
}

void IOchannel::enable_reading() {
    _proxy->enable_reading();
    _update();
}

void IOchannel::enable_writing() {
    _proxy->enable_writing();
    _update();
}

bool IOchannel::is_idling() const {
    return _proxy->is_idling();
}

bool IOchannel::is_reading() const {
    return _proxy->is_reading();
}

bool IOchannel::is_writing() const {
    return _proxy->is_writing();
}

void IOchannel::remove() {
    assert(is_idling());
    _inLoop = false;
    _proxy->eventloopProxy().remove(*_proxy);
}

void IOchannel::tie(const std::shared_ptr<void> &obj) {
    _proxy->tie(obj);
}

void IOchannel::_update() {
    _inLoop = true;
    _proxy->eventloopProxy().update(*_proxy);
}
